package com.dg.gaming.client;

import java.io.*;
import java.net.*;

import com.dg.gaming.api.common.*;
import com.dg.gaming.api.common.msg.*;
import nanoxml.*;

public class TableConnection extends AbstractConnectionThread implements
        Runnable {

    /** Interface betweem this thread and the Frame */
    protected IClient clientInterface;

    /** Current game ID. */
    protected String gameID = null;

    /** Socket between the server and the user. */
    protected Socket socket;

    /** Buffered input. */
    protected BufferedReader in;

    /** PrintStream for the output. */
    private PrintStream out;
    private Table table;
    private TableConnectionThread tableConn;
    private String userName;

    /**
     * Default constructor which takes a Socket connection to the server, a
     * username and an IClient which sits between this class and the GUI.
     *
     * @param connection       Socket connection to server.
     * @param username         Username
     * @param clientInterface  Interface between this class and GUI.
     */
    public TableConnection(Socket connection, long userid,
                           IClient clientInterface) {
        super();
        this.clientInterface = clientInterface;

        this.userid = userid;
        try {
            setSocket(connection);
        } catch (IOException ex) {
        }

    }

    protected void setSocket(Socket socket) throws IOException {
        this.socket = socket;

        if (socket != null) {
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new PrintStream(socket.getOutputStream());
        }
    }


    /**
     * Set the client interface.
     *
     * @param clientInterface  Client interface
     */
    public void setClientInterface(IClient clientInterface) {
        this.clientInterface = clientInterface;
    }

    public void setTable(Table table) {
        this.table = table;
        this.tableConn = new TableConnectionThread(this, table.getTableNum());
        Game game = table.getGame();
        game.getTableList().addTable(table);

    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    /**
     * Parse method which reads the first token of the message and delegate
     * to the implementating client.
     *
     * @see com.dg.gaming.api.common.AbstractConnectionThread#parse(nanoxml.XMLElement)
     */
    public void parse(XMLElement message) {
        // Update data first of all

        if (table == null) {
            this.clientInterface.receiveGameMessage(message);
        } else {
            this.clientInterface.receiveTableMessage(message, table.getTableNum());
        }

    }

    /**
     * Send a ITransmittable object from a client to the server.
     *
     * @param message
     */
    public void send(MsgGameMessage message) {
        this.send((ITransmittable) message);
    }

    /**
     * Run method - runs until an exception has occured or the loop variable
     * becomes false.
     *
     * @see java.lang.Runnable#run()
     */
    public void run() {

        try {
            while (loop) {
                // listen for input from the user
                String inString = "";

                while (loop && inString != null && inString.equals("")) {
                    if (in == null) {
                        cleanup();
                        return;
                    }
                    inString = in.readLine();
//
//                    int aval = in.available();
//                    if (aval > 0) {
//                        byte[] bt = new byte[aval];
//                        in.read(bt);
//                        inString = new String(bt, "UTF8");
//                    } else {
//                        inString = "";
//                    }
                }

                // Check input.
                if (in == null) {
                    cleanup();
                    return;
                }

                // Ensure that the communication is XML (starts with a '<' character)
                // as any sort of client could send communication to the server.
                if (inString != null) {
                    if (inString.startsWith("<")) {
                        System.out.println(inString);
                        // Starts with an '<' so try and parse this XML
                        XMLElement message = new XMLElement();

                        try {
                            message.parseString(inString);

                            // parse this element
                            if (message != null) {
                                parse(message);
                            }
                        } catch (XMLParseException xmlParseEx) {
                        }
                    }
                }
            }
        } catch (SocketException sEx) {
        } catch (IOException ioEx) {
        } catch (Exception genEx) {
            genEx.printStackTrace();
        }

        connected = false;
        cleanup();
    }

    public void send(ITransmittable transObject) {
        // Retrieve XMLElement from the object and flatten to a String.
        String message = transObject.flatten().toString();

        // Send down the socket to the receiving end
        try {
//            System.out.println(message);
            out.write(message.getBytes("UTF8"));
            try {
                Thread.currentThread().sleep(10);
            } catch (InterruptedException ex1) {
            }
        } catch (IOException ex) {
        }
    }

    public void cleanup() {
        // Clean up
    }

    public Table getTable() {
        return table;
    }

    public TableConnectionThread getTableConn() {
        return tableConn;
    }

    public String getUserName() {
        return userName;
    }

    /**
     * getTableNum
     *
     * @return String
     */
    public String getTableNum() {
        return table.getTableNum();
    }



    /**
     * getGame
     *
     * @return Game
     */
    public Game getGame() {
        return table.getGame();
    }

    @Override
    public long getUserId() {
        return userid;
    }

}
